<?php
/**
 * Created by PhpStorm.
 * User: ari
 * Date: 10/18/14
 * Time: 2:51 PM
 */
namespace BC\Games\Holdem;

use BC\SiteIndex;
use CPath\Build\IBuildable;
use CPath\Build\IBuildRequest;
use CPath\Data\Map\CallbackSequenceMapper;
use CPath\Data\Map\ISequenceMapper;
use CPath\Render\HTML\Element\Form\HTMLButton;
use CPath\Render\HTML\Element\Form\HTMLForm;
use CPath\Render\HTML\Element\Form\HTMLInputField;
use CPath\Render\HTML\Element\HTMLElement;
use CPath\Render\HTML\Header\HTMLMetaTag;
use CPath\Render\HTML\HTMLContainer;
use CPath\Request\Exceptions\RequestException;
use CPath\Request\Executable\IExecutable;
use CPath\Request\IRequest;
use CPath\Response\IResponse;
use CPath\Route\IRoutable;
use CPath\Route\RouteBuilder;

class HoldemRoute implements IRoutable, IBuildable, IExecutable
{
	const PARAM_SEARCH = 'search';
	const PARAM_PUBLIC = 'public';

	const PATH_FORMAT   = 'games/holdem/';

	/** @var HTMLForm[] */
	private $pForm = array();
	/** @var HTMLElement[] */
	private $mElm = array();
	/** @var HTMLInputField[] */
	private $mInput = array();
	private $mRequest;

	public function __construct(IRequest $Request) {
		$this->mRequest = $Request;
		$this->mContents = new HTMLContainer(
			$this->pForm['form-holdem-search'] = new HTMLForm('GET', self::PATH_FORMAT . 'search/',
				new HTMLMetaTag(HTMLMetaTag::META_TITLE, 'Texas Holdem Search'),

				$this->mElm['fieldset-search'] = new HTMLElement('fieldset', 'fieldset-search',
					new HTMLElement('legend', 'legend-search', 'Search holdem tables'),

					'Search',
					$this->mInput['field-search'] = new HTMLInputField(self::PARAM_SEARCH)
				),

				$this->mElm['fieldset-search-results'] = new HTMLElement('fieldset', 'fieldset-search-results',
					new HTMLElement('legend', 'legend-search', 'Search results')
				)
			),


			new HoldemInvite(),

			$this->pForm['form-holdem-join'] = new HTMLForm('GET', self::PATH_FORMAT . 'join/',

				$this->mElm['fieldset-join'] = new HTMLElement('fieldset', 'fieldset-join',
					new HTMLElement('legend', 'legend-join', 'Join an active table'),

					"Join",
					$this->mElm['field-join'] = new HTMLButton('join', "Join")
				)
			)

		);
		foreach($this->mElm + $this->mInput as $class => $Elm)
			$Elm->addClass($class);

	}

	/**
	 * Execute a command and return a response. Does not render
	 * @param null|IRequest $Request
	 * @throws \CPath\Request\Exceptions\RequestException
	 * @return IResponse the execution response
	 */
	function execute(IRequest $Request) {
		$search = $this->mInput['field-search']->validate($Request);

		if($search) {
			$Results = $this->mElm['fieldset-search-results'];
			$this->mapSequence(
				new CallbackSequenceMapper(
					function(HoldemTable $Table) use ($Results) {
						$Results->addContent($Table);
					}
				),
				$search
			);
		} else {
			$this->mElm['fieldset-search-results']->setStyle('display', 'none');
		}

		return $this->mContents;
	}

	/**
	 * Map sequential data to the map
	 * @param ISequenceMapper $Map
	 * @param null $search
	 * @param int $limit
	 */
	function mapSequence(ISequenceMapper $Map, $search=null, $limit=10) {
		if(strpos($search, '*') === false)
			$search .= '*';

		$search        = sprintf(self::PATH_FORMAT, $search);
		$Request = $this->mRequest;
		foreach(glob($search) as $path) {
			$tableID = basename($path);
			$Map->mapNext(new HoldemTable($Request, $tableID));
			if($limit-- <= 0)
				break;
		}
	}


	// Static

	/**
	 * Handle this request and render any content
	 * @param IBuildRequest $Request the build request inst for this build session
	 * @return void
	 * @build --disable 0
	 * Note: Use doctag 'build' with '--disable 1' to have this IBuildable class skipped during a build
	 */
	static function handleBuildStatic(IBuildRequest $Request) {
		$Routes = new RouteBuilder($Request, new SiteIndex());
		$Routes->writeRoute('ANY /' . self::PATH_FORMAT, __CLASS__);
	}

	/**
	 * Route the request to this class object and return the object
	 * @param IRequest $Request the IRequest inst for this render
	 * @param Object[]|null $Previous all previous response object that were passed from a handler, if any
	 * @param null|mixed $_arg [varargs] passed by route map
	 * @throws Exceptions\TableExistsException
	 * @throws RequestException
	 * @return void|bool|Object returns a response object
	 * If nothing is returned (or bool[true]), it is assumed that rendering has occurred and the request ends
	 * If false is returned, this static handler will be called again if another handler returns an object
	 * If an object is returned, it is passed along to the next handler
	 */
	static function routeRequestStatic(IRequest $Request, Array &$Previous = array(), $_arg=null) {
		return new HoldemRoute($Request);
	}
}

